package com.qf.base.utils;


import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Optional;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 压缩文件工具类
 */
public class ZipUtil {
    private static final int BUFFER_SIZE=2*1024;

    /**
     * 压缩文件 指定压缩包位置
     * @param srcDir
     * @param out
     * @param keepDirStructure
     */
    public static void toZip(String srcDir, OutputStream out,boolean keepDirStructure){
        long start =System.currentTimeMillis();
        ZipOutputStream zos=new ZipOutputStream(out);
        File sourceFile=new File(srcDir);
        try {
            compress(sourceFile,zos,sourceFile.getName(),keepDirStructure);
            long end=System.currentTimeMillis();
            System.out.println("压缩完成，耗时"+(end-start)+"时间");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (zos!=null){
                try {
                    zos.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
    public static void toZip(String tempFolderPath, HttpServletResponse rep){
        //压缩文件夹
        OutputStream out=null;
        try {
            out=new BufferedOutputStream(rep.getOutputStream());
            ZipUtil.toZip(tempFolderPath,out,false);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            ZipUtil.delAllFile(new File(tempFolderPath));
            if (out!=null){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 递归压缩方法
     * @param sourceFile 源文件
     * @param zos   zip输出流
     * @param name  压缩后的名称
     * @param keepDirStructure  是否保留原来的目录结构 true 保留目录结构
     *                          false 所有文件跑到压缩包根目录下（注意  不保留目录结构可能会出现同名文件，会压缩失败）
     * @throws IOException
     */
    public static void compress(File sourceFile,ZipOutputStream zos,String name,boolean keepDirStructure) throws IOException {
        byte[] buf=new byte[BUFFER_SIZE];
        if (sourceFile.isFile()){
            //向zip输出流中添加一个zip实体，构造器中name为zip实体的文件的名字
            zos.putNextEntry(new ZipEntry(name));
            //copy文件到zip输出流中
            int len;
            FileInputStream in=new FileInputStream(sourceFile);
            while ((len=in.read(buf))!=-1){
                zos.write(buf,0,len);
            }
            zos.closeEntry();
            in.close();
        }else {
            //如果是文件夹
            File[] listFiles=sourceFile.listFiles();
            if (listFiles==null||listFiles.length==0){
                //需要保留原来的文件夹时，需要对空文件夹进行处理
                if (keepDirStructure){
                    //空文件夹的处理
                    zos.putNextEntry(new ZipEntry(name+"/"));
                    //没有文件  不需要文件的copy
                    zos.closeEntry();
                }
            }else {
                for (File file:listFiles){
                    //判断是否需要保留原来的结构
                    if (keepDirStructure){
                        compress(file,zos,name+File.separator+file.getName(),keepDirStructure);
                    }else {
                        compress(file,zos, file.getName(), keepDirStructure);
                    }
                }
            }
        }
    }
    public static void delAllFile(File directory){
        if (directory.isFile()){
            boolean ret=directory.delete();
            if (!ret){
                System.out.println("删除失败");
            }
        }else {
            File[] files= Optional.ofNullable(directory.listFiles()).orElse(new File[0]);
            //空文件夹
            if (files.length==0){
                boolean delEmptyFlag=directory.delete();
                if (!delEmptyFlag){
                    System.out.println("删除失败");
                }
            }
            //删除子文件夹和文件
            for (File file:files){
                if (file.isDirectory()){
                    delAllFile(file);
                }else {
                    boolean aa=file.delete();
                    if (!aa){
                        System.out.println("删除失败");
                    }
                }
            }
            //删除文件本身
            boolean delFlag=directory.delete();
            if (!delFlag){
                System.out.println("删除失败");
            }
        }
    }
}
